package de.mrapp.tabswitcher;

import de.mrapp.ohos_util.view.AbstractViewHolderAdapter;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.app.Context;
import ohos.utils.PacMap;
import ohos.utils.Sequenceable;

import java.util.ArrayList;

public abstract class TabSwitcherDecorator extends AbstractViewHolderAdapter {

    /**
     * The name of the extra, which is used to store the state of a view hierarchy within a bundle.
     */
    private static final String VIEW_HIERARCHY_STATE_EXTRA =
            TabSwitcherDecorator.class.getName() + "::ViewHierarchyState";

    /**
     * The method which is invoked, when a view, which is used to visualize a tab, should be
     * inflated.
     *
     * @param inflater The inflater, which should be used to inflate the view, as an instance of the class
     *                 {@link LayoutScatter}. The inflater may not be null
     * @param parent   The parent view of the view, which should be inflated, as an instance of the class
     *                 {@link ohos.agp.components.ComponentContainer} or null, if no parent view is available
     * @param viewType The view type of the tab, which should be visualized, as an {@link Integer} value
     * @return The view, which has been inflated, as an instance of the class {@link Component}. The view
     * may not be null
     */

    public abstract Component onInflateView(final LayoutScatter inflater,
                                       final ComponentContainer parent, final int viewType);

    /**
     * The method which is invoked, when the view, which is used to visualize a tab, should be
     * shown, respectively when it should be refreshed. The purpose of this method is to customize
     * the appearance of the view, which is used to visualize the corresponding tab, depending on
     * its state and whether the tab switcher is currently shown, or not.
     *
     * @param context            The context, the tab switcher belongs to, as an instance of the class {@link
     *                           Context}. The context may not be null
     * @param tabSwitcher        The tab switcher, whose tabs are visualized by the decorator, as an instance of the
     *                           type {@link TabSwitcher}. The tab switcher may not be null
     * @param view               The view, which is used to visualize the tab, as an instance of the class {@link
     *                           Component}. The view may not be null
     * @param tab                The tab, which should be visualized, as an instance of the class {@link Tab}. The tab
     *                           may not be null
     * @param index              The index of the tab, which should be visualized, as an {@link Integer} value
     * @param viewType           The view type of the tab, which should be visualized, as an {@link Integer} value
     * @param savedInstanceState The bundle, which has previously been used to save the state of the view as an
     *                           instance of the class {@link PacMap} or null, if no saved state is available
     */
    public abstract void onShowTab(final Context context,
                                   final TabSwitcher tabSwitcher, final Component view,
                                   final Tab tab, final int index, final int viewType,
                                   final PacMap savedInstanceState);

    /**
     * The method, which is invoked, when the view, which is used to visualize a tab has been
     * recycled. The purpose of this method is to reset the appearance of the view to the default
     * state, as it might still display the content of tab for which it was previously used. This
     * method is called prior to invoking the method {@link #onShowTab(Context, TabSwitcher, Component,
     * Tab, int, int, PacMap)}.
     *
     * @param context            The context, the tab switcher belongs to, as an instance of the class {@link
     *                           Context}. The context may not be null
     * @param tabSwitcher        The tab switcher, whose tabs are visualized by the decorator, as an instance of the
     *                           type {@link TabSwitcher}. The tab switcher may not be null
     * @param view               The view, which is used to visualize the tab, as an instance of the class {@link
     *                           Component}. The view may not be null
     * @param tab                The tab, which should be visualized, as an instance of the class {@link Tab}. The tab
     *                           may not be null
     * @param index              The index of the tab, which should be visualized, as an {@link Integer} value
     * @param viewType           The view type of the tab, which should be visualized, as an {@link Integer} value
     * @param savedInstanceState The bundle, which has previously been used to save the state of the view as an
     *                           instance of the class {@link PacMap} or null, if no saved state is available
     */
    public void onRecycleView(final Context context,
                              final TabSwitcher tabSwitcher, final Component view,
                              final Tab tab, final int index, final int viewType,
                              final PacMap savedInstanceState) {

    }

    /**
     * The method, which is invoked, when the view, which is used to visualize a tab, is removed.
     * The purpose of this method is to save the current state of the tab in a bundle.
     *
     * @param view     The view, which is used to visualize the tab, as an instance of the class {@link
     *                 Component}
     * @param tab      The tab, whose state should be saved, as an instance of the class {@link Tab}. The
     *                 tab may not be null
     * @param index    The index of the tab, whose state should be saved, as an {@link Integer} value
     * @param viewType The view type of the tab, whose state should be saved, as an {@link Integer} value
     * @param outState The bundle, the state of the tab should be saved to, as an instance of the class
     *                 {@link PacMap}. The bundle may not be null
     */
    public void onSaveInstanceState(final Component view, final Tab tab,
                                    final int index, final int viewType,
                                    final PacMap outState) {

    }

    /**
     * Returns the view type, which corresponds to a specific tab. For each layout, which is
     * inflated by the <code>onInflateView</code>-method, a distinct view type must be returned.
     *
     * @param tab   The tab, whose view type should be returned, as an instance of the class {@link Tab}.
     *              The tab may not be null
     * @param index The index of the tab, whose view type should be returned, as an {@link Integer}
     *              value
     * @return The view type, which corresponds to the given tab, as an {@link Integer} value
     */
    public int getViewType(final Tab tab, final int index) {
        return 0;
    }

    /**
     * Returns the number of view types, which are used by the decorator.
     *
     * @return The number of view types, which are used by the decorator, as an {@link Integer}
     * value. The number of view types must correspond to the number of distinct values, which are
     * returned by the <code>getViewType</code>-method
     */
    public int getViewTypeCount() {
        return 1;
    }

    /**
     * The method, which is invoked by a {@link TabSwitcher} to inflate the view, which should be
     * used to visualize a specific tab.
     *
     * @param inflater The inflater, which should be used to inflate the view, as an instance of the class
     *                 {@link LayoutScatter}. The inflater may not be null
     * @param parent   The parent view of the view, which should be inflated, as an instance of the class
     *                 {@link ComponentContainer} or null, if no parent view is available
     * @param tab      The tab, which should be visualized, as an instance of the class {@link Tab}. The tab
     *                 may not be null
     * @param index    The index of the tab, which should be visualized, as an {@link Integer} value
     * @return The view, which has been inflated, as an instance of the class {@link Component}. The view
     * may not be null
     */

    public final Component inflateView(final LayoutScatter inflater,
                                       final ComponentContainer parent, final Tab tab,
                                       final int index) {
        int viewType = getViewType(tab, index);
        return onInflateView(inflater, parent, viewType);
    }

    /**
     * The method, which is invoked by a {@link TabSwitcher} to apply the decorator. It initializes
     * the view holder pattern, which is provided by the decorator and then delegates the method
     * call to the decorator's custom implementation of the method <code>onShowTab(...):void</code>.
     *
     * @param context            The context, the tab switcher belongs to, as an instance of the class {@link
     *                           Context}. The context may not be null
     * @param tabSwitcher        The tab switcher, whose tabs are visualized by the decorator, as an instance of the
     *                           class {@link TabSwitcher}. The tab switcher may not be null
     * @param view               The view, which is used to visualize the tab, as an instance of the class {@link
     *                           Component}. The view may not be null
     * @param tab                The tab, which should be visualized, as an instance of the class {@link Tab}. The tab
     *                           may not be null
     * @param index              The index of the tab, which should be visualized, as an {@link Integer} value
     * @param savedInstanceState The bundle, which has previously been used to save the state of the view as an
     *                           instance of the class {@link PacMap} or null, if no saved state is available
     * @param inflated           True, if the view has been inflated, false, if it has been reused
     */
    public final void applyDecorator(final Context context,
                                     final TabSwitcher tabSwitcher,
                                     final Component view, final Tab tab,
                                     final int index, final PacMap savedInstanceState,
                                     final boolean inflated) {

        setCurrentParentView(view);
        int viewType = getViewType(tab, index);

        if (savedInstanceState != null) {
            ArrayList<Sequenceable> viewStates =
                    savedInstanceState.getSequenceableList(VIEW_HIERARCHY_STATE_EXTRA);

            if (viewStates != null) {
//                view.restoreHierarchyState(viewStates);
            }
        }

        if (!inflated) {
            onRecycleView(context, tabSwitcher, view, tab, index, viewType, savedInstanceState);
        }

        onShowTab(context, tabSwitcher, view, tab, index, viewType, savedInstanceState);
    }

    /**
     * The method, which is invoked by a {@link TabSwitcher} to save the current state of a tab. It
     * initializes the view holder pattern, which is provided by the decorator and then delegates
     * the method call to the decorator's custom implementation of the method
     * <code>onSaveInstanceState(...):void</code>.
     *
     * @param view  The view, which is used to visualize the tab, as an instance of the class {@link
     *              Component}
     * @param tab   The tab, whose state should be saved, as an instance of the class {@link Tab}. The
     *              tab may not be null
     * @param index The index of the tab, whose state should be saved, as an {@link Integer} value
     * @return The bundle, which has been used to save the state, as an instance of the class {@link
     * PacMap}. The bundle may not be null
     */

    public final PacMap saveInstanceState(final Component view, final Tab tab,
                                          final int index) {
        setCurrentParentView(view);
        int viewType = getViewType(tab, index);
        PacMap outState = new PacMap();
        ArrayList<Sequenceable> viewStates = new ArrayList<>();
        //找不到对应方法，暂时注释, 用于分发保存的状态数据，到子View
//        view.saveHierarchyState(viewStates);
        outState.putSequenceableObjectList(VIEW_HIERARCHY_STATE_EXTRA, viewStates);
        onSaveInstanceState(view, tab, index, viewType, outState);
        return outState;
    }
}
